/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package dawnland02.model.entity;

import dawnland02.data.map.model.MatrixCell;
import dawnland02.data.map.model.MatrixDirection;
import javafx.async.JavaTaskBase;

import dawnland02.model.entity.attribute.PhysicalAttribute;
import dawnland02.model.quest.Quest;
import dawnland02.model.quest.QuestParam;
import dawnland02.model.quest.QuestType;
import dawnland02.model.task.Task;
import dawnland02.model.task.impl.BuildRoadToDestinationTask;
import dawnland02.model.task.impl.MoveToTask;
import dawnland02.service.GeneralService;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Petru Obreja (obrejap@yahoo.com)
 */
public class EntityImpl implements EntityInternal{

    private Integer id;
    private Integer x;
    private Integer y;
    private MatrixCell matrixCell;
    private MatrixDirection direction;
    private Map<PhysicalAttribute, Double> physicalAttributes;

    private JavaTaskBase javaTaskBase;
    private UIEntityActionHandler uiEntityActionHandler;

    private boolean duringAction;

    public EntityImpl(Integer id, Integer x, Integer y) {
        this.id = id;
        setCoordinates(x, y);
        duringAction = false;
        physicalAttributes = new HashMap<PhysicalAttribute, Double>();
        for(PhysicalAttribute physicalAttribute : PhysicalAttribute.values()){
            physicalAttributes.put(physicalAttribute, 1.0);
        }
        direction = MatrixDirection.UP;
    }

    @Override
    public Integer getId() {
        return id;
    }

    @Override
    public Integer getX() {
        return x;
    }

    @Override
    public Integer getY() {
        return y;
    }
    
    @Override
    public void setCoordinates(Integer x, Integer y) {
        this.x = x;
        this.y = y;
        matrixCell = GeneralService.getMatrix().getNode(x, y);
    }

    @Override
    public MatrixCell getMatrixCell(){
        return matrixCell;
    }

    @Override
    public MatrixDirection getDirection() {
        return direction;
    }

    @Override
    public void setDirection(MatrixDirection direction) {
        this.direction = direction;
    }

    @Override
    public Map<PhysicalAttribute, Double> getPhysicalAttributes() {
        return physicalAttributes;
    }

    @Override
    public Double getPhysicalAttribute(PhysicalAttribute physicalAttribute) {
        return physicalAttributes.get(physicalAttribute);
    }

    @Override
    public void setPhysicalAttribute(PhysicalAttribute physicalAttribute, Double value) {
        physicalAttributes.put(physicalAttribute, value);
    }

    @Override
    public boolean isDuringAction() {
        return duringAction;
    }

    @Override
    public void setDuringAction(boolean duringAction) {
        this.duringAction = duringAction;
    }

    @Override
    public synchronized void notify(final Quest quest) {
        System.out.println("Notified about "+quest);
        if(!duringAction){
            //computation needs to be done outside EDT (Event Dispatch Thread)
            Task task;
            if(quest.getQuestType() == QuestType.MOVE_TO){
                Integer moveToDestination = (Integer) quest.getParam(QuestParam.MOVE_TO_DESTINATION);
                task = new MoveToTask(this, moveToDestination);
            } else if(quest.getQuestType() == QuestType.BUILD_ROAD_TO){
                Integer buildToDestination = (Integer) quest.getParam(QuestParam.BUILD_ROAD_TO_DESTINATION);
                task = new BuildRoadToDestinationTask(this, buildToDestination);
            } else {
                return;
            }
            task.execute();
        }
    }

    @Override
    public void run() throws Exception {
        System.out.println("Entity started to run.");
        /*while(true){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                Logger.getLogger(EntityImpl.class.getName()).log(Level.SEVERE, null, ex);
            }
        }*/
        /*Entry.deferAction(new Runnable() { //deferAction will be run in EDT (Event Dispatch Thread)
            @Override
            public void run() {
                System.out.println("Entity started to run.");
                while(true){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(EntityImpl.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        });*/
    }

    @Override
    public void setJavaTaskBase(JavaTaskBase javaTaskBase) {
        this.javaTaskBase = javaTaskBase;
    }

    private JavaTaskBase getJavaTaskBase() {
        if(javaTaskBase == null) {
            throw new IllegalStateException("javaTaskBase wasn't initialized");
        }
        return javaTaskBase;
    }

    @Override
    public void setUIEntityActionHandler(UIEntityActionHandler uiEntityActionHandler) {
        this.uiEntityActionHandler = uiEntityActionHandler;
    }

    @Override
    public UIEntityActionHandler getUIEntityActionHandler() {
        if(uiEntityActionHandler == null) {
            throw new IllegalStateException("uiEntityActionHandler wasn't initialized");
        }
        return uiEntityActionHandler;
    }

    @Override
    public void start() {
        getJavaTaskBase().start();
    }

    @Override
    public void stop() {
        getJavaTaskBase().stop();
    }

}
